package syncmap

import (
	"sync"

	"lux/internal/json"
)

type SyncMap struct {
	mm map[interface{}]interface{}
	mu sync.RWMutex
}

func New(mm map[interface{}]interface{}) *SyncMap {
	if mm == nil {
		mm = make(map[interface{}]interface{})
	}

	return &SyncMap{
		mm: mm,
	}
}

func (m *SyncMap) Get(key interface{}) (value interface{}, ok bool) {
	m.mu.RLock()
	defer m.mu.RUnlock()

	value, ok = m.mm[key]
	return
}

func (m *SyncMap) GetString(key string) string {
	if val, ok := m.Get(key); ok && val != nil {
		s, _ := val.(string)
		return s
	}

	return ""
}

func (m *SyncMap) Set(key, value interface{}) {
	m.mu.Lock()
	defer m.mu.Unlock()

	m.mm[key] = value
}

func (m *SyncMap) Delete(key interface{}) {
	m.mu.Lock()
	defer m.mu.Unlock()

	delete(m.mm, key)
}

func (m *SyncMap) Range(f func(key, value interface{}) bool) {
	m.mu.RLock()
	defer m.mu.RUnlock()

	for k, v := range m.mm {
		if !f(k, v) {
			return
		}
	}
}

func (m *SyncMap) MarshalJSON() ([]byte, error) {
	m.mu.RLock()
	defer m.mu.RUnlock()

	return json.Marshal(m.mm)
}

func (m *SyncMap) UnmarshalJSON(data []byte) error {
	m.mu.Lock()
	defer m.mu.Unlock()

	if m.mm == nil {
		m.mm = make(map[interface{}]interface{})
	}

	t := make(map[string]interface{})
	err := json.Unmarshal(data, &t)
	if err != nil {
		return err
	}

	for k, v := range t {
		m.mm[k] = v
	}
	return nil
}
